package com.chen.common.util;



import com.chen.common.consts.Const;
import com.chen.common.model.OP;

import java.math.BigInteger;
import java.util.*;
import java.util.function.Supplier;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;

/**
 * 字符串工具
 * <p>
 * <p>
 * 常用正则表达式：
 * ([0-9]+[层楼])
 *
 * @author chenzy
 * @see <a href='https://www.runoob.com/java/java-regular-expressions.html'>正则表达式语法参考</a>
 * @since 2019.12.19
 */
public class StringUtil {

    private StringUtil() {
    }

    public static String add(Object... strings) {
        var data = new StringBuilder();
        for (var s : strings) {
            data.append(s);
        }
        return data.toString();
    }

    /**
     * 文本的长度不够时，前缀填充指定字符串
     *
     * @param text 文本
     * @param fill 填充字符串
     * @param length 文本长度不够时填充
     * @return 填充后的文本
     */
    public static String fillPrefix(String text, String fill, int length) {
        if (text == null) {
            text = "";
        }
        return text.length() < length ? fill.repeat(length - text.length()).concat(text) : text;
    }

    /**
     * 文本不是指定字符结尾时,补上指定字符
     * @param text 文本
     * @param fill 填充字符串
     * @return 填充后的文本
     */
    public static String fillLast(String text,String fill){
        if (text==null){
            return text;
        }
        return text.endsWith(fill)?text:text.concat(fill);
    }

    /**
     * 文本的长度不够时，后缀填充指定字符串
     *
     * @param text 文本
     * @param fill 填充字符串
     * @param length 文本长度不够时填充
     * @return 填充后的文本
     */
    public static String fillSuffix(String text, String fill, int length) {
        if (text == null) {
            text = "";
        }
        return text.length() < length ? text.concat(fill.repeat(length - text.length())) : text;
    }

    /**
     * 每隔size位插入字符 spit
     *
     * @return 插入后的字符串
     */
    public static String insert(String text, int size, char spit) {
        if (isBlank(text)) {
            return text;
        }
        return text.replaceAll("(.{" + size + "})", spit + "$1").substring(1);
    }

    public static String getUUID() {
        var uuid = UUID.randomUUID();

        char[] dest = new char[32];
        char[] src = uuid.toString().toCharArray();
        System.arraycopy(src, 0, dest, 0, 8);
        System.arraycopy(src, 9, dest, 8, 4);
        System.arraycopy(src, 14, dest, 12, 4);
        System.arraycopy(src, 19, dest, 16, 4);
        System.arraycopy(src, 24, dest, 20, 12);
        return new String(dest);
    }

    /*匹配到任意一个非空白字符就说明不是空白字符串就返回true*/
    public static Boolean isNotBlank(String str) {
        if (str == null) {
            return false;
        }
        return !isBlank(str);
//        return str.chars().anyMatch(value -> !Character.isWhitespace(value));
    }

    public static boolean isNotBlankAnd(String... strs) {
        if (ListUtil.isEmpty(strs)) {
            return false;
        }
        return Arrays.stream(strs).allMatch(StringUtil::isNotBlank);
    }

    public static boolean isNotBlankOr(String... strs) {
        if (ListUtil.isEmpty(strs)) {
            return false;
        }
        return Arrays.stream(strs).anyMatch(StringUtil::isNotBlank);
    }

    public static boolean isBlankAnd(String... strs) {
        if (ListUtil.isEmpty(strs)) {
            return true;
        }
        return Arrays.stream(strs).allMatch(StringUtil::isBlank);
    }

    public static Boolean isBlank(String str) {
        return str == null||str.isBlank();
//        return str.chars().allMatch(Character::isWhitespace);
    }

    /*两个参数 有一个为空时返回true。都为空或者都不为空时返回false */
    public static boolean isBlankXOR(String s1, String s2) {
        return isBlank(s1) ^ isBlank(s2);
    }

    /*匹配任意一个非空对象就返回true*/
    public static Boolean isBlankOr(String... strs) {
        if (ListUtil.isEmpty(strs)) {
            return true;
        }
        return Arrays.stream(strs).anyMatch(StringUtil::isBlank);
    }

    public static <E extends Throwable> void blankThrow(Supplier<? extends E> throwSupplier, String... strs) throws E {
        if (isBlankOr(strs)) {
            throw throwSupplier.get();
        }
    }


    public static String getStr(Object value) {
        return getStr(value, "");
    }

    public static String getStr(Object value, String defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        return value.toString();
    }

    public static String getStr(Number value, int length) {
        if (value == null) {
            value = 0;
        }
        var data = new StringBuilder(value.toString());
        while (length > data.length()) {
            data.insert(0, "0");
        }
        return data.toString();
    }

    /**
     * 转换boolean 0表示true 其他false
     * 字符串true表示true 其他false
     */
    public static Boolean getBoolean(String value) {
        if (isBlank(value)) {
            return false;
        }
        return value.equals("" + Const.trueInt) || value.equalsIgnoreCase("true");
    }

    public static Boolean getBoolean(Integer value) {
        if (value == null) {
            return false;
        }
        return value.equals(Const.trueInt);
    }

    /**
     * 转换成boolean值 0表示true 其他false
     * 字符串true表示true 其他false
     */
    public static Boolean getBoolean(Object value) {
        return getBoolean(value, false);
    }

    /**
     * 转换成boolean值 1表示true 其他false
     * 字符串true表示true 其他false
     */
    public static Boolean getBoolean(Object value, Boolean defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        return getBoolean(value.toString());
    }

    /**
     * boolean值转int
     * true=》 1 false=》0
     */
    public static Integer getInt(Boolean value) {
        return value ? Const.trueInt : Const.falseInt;
    }

    public static Integer getInt(Boolean value, Integer defaultValue) {
        if (value == null) {
            return null;
        }
        return value ? Const.trueInt : Const.falseInt;
    }

    public static Integer getInt(Object value) {
        return getInt(value, 0);
    }

    /**
     * 对象转Integer,null返回null
     */
    public static Integer getInt(Object value, Integer defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof Integer) {
            return (Integer) value;
        }
        return Integer.parseInt(value.toString());
    }
    public static Integer getInt(String value, Integer defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        try {
            return Integer.parseInt(value);
        } catch (NumberFormatException e){
            return defaultValue;
        }
    }
    public static OP<Integer> getInt(String value){
        if (value==null){
            return OP.empty();
        }
        try {
            return OP.of(Integer.parseInt(value));
        }catch (Exception e){
            return OP.empty();
        }
    }

    public static Long getLong(Object value) {
        return getLong(value, 0L);
    }

    public static Long getLong(Object value, Long defaultValue) {
        if (value == null) {
            return defaultValue;
        }
        if (value instanceof Long) {
            return (Long) value;
        }
        var valueString = value.toString().trim();
        if (valueString.isEmpty()) {
            return defaultValue;
        }
        return Long.valueOf(valueString);
    }

    /**
     * 字符串首字母大写
     */
    public static String upFirst(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        // 进行字母的ascii编码前移，效率要高于截取字符串进行转换的操作
        char[] cs = str.toCharArray();
        if (cs[0] >= 'a' && cs[0] <= 'z') {
            cs[0] -= 32;
            return String.valueOf(cs);
        } else {
            return str;
        }
    }

    /**
     * 十进制数=>十六进制数，不够指定位数就在前面补零。超过位数不截取
     *
     * @param num    十进制数
     * @param digits 位数，转成多少位的十六进制数
     */
    public static String decimal2Hex(Integer num, int digits) {
        return String.format("%0" + digits + "x", num).toUpperCase();
    }

    public static String decimal2Hex(Long num, int digits) {
        return String.format("%0" + digits + "x", num).toUpperCase();
    }


    /**
     * 十六进制数=>十进制数，不够指定位数就在前面补零。超过位数不截取
     *
     * @param digits 位数，转成多少位的十进制数
     */
    public static String hex2Decimal(String hexStr, int digits) {
        return String.format("%0" + digits + "d", new BigInteger(hexStr, 16), true);
    }

    /**
     * 十六进制数转十进制数，不够指定位数就在前面补零。
     * 如果不允许超出位数，则返回0
     *
     * @param allowExceedDigits 为false且超出长度将返回指定位数的0
     */
    public static String hex2Decimal(String hexStr, int digits, Boolean allowExceedDigits) {
        String result = String.format("%0" + digits + "d", new BigInteger(hexStr, 16));
        if (!allowExceedDigits && result.length() > digits) {
            return String.format("%0" + digits + "d", 0);
        }
        return result;
    }

    /**
     * 驼峰转下划线
     */
    public static String humpToLine(String str) {
        var matcher = Pattern.compile("[A-Z]").matcher(str);
        var result = new StringBuilder();
        while (matcher.find()) {
            matcher.appendReplacement(result, (matcher.start()==0?"":"_") + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(result);
        return result.toString();
    }

    /**
     * 字符串中的unicode字符转成中文,如"abc\u6211\u662f\u4e16\u754c12312"=>"abc我是世界12312"
     * @param str 待转换的字符串
     * @return 转换后的字符串
     */
    @SuppressWarnings("UnnecessaryUnicodeEscape")
    public static String convertUnicodeToChinese(String str) {
        String patternS = "\\\\u[0-9a-fA-F]{4}";
        var matcher = Pattern.compile(patternS).matcher(str);
        var sb = new StringBuilder();
        while (matcher.find()) {
            var hex=matcher.group();
            int hexInt = Integer.parseInt(hex.substring(2), 16);
            char hexChar = (char) hexInt;
            matcher.appendReplacement(sb, Character.toString(hexChar));
        }
        matcher.appendTail(sb);
        return sb.toString();
    }
    public static List<Integer> match(String str, String patternS) {
        var matcher = Pattern.compile(patternS).matcher(str);
        var result = new ArrayList<Integer>();
        while (matcher.find()) {
            result.add(matcher.start());
        }
        return result;
    }

    /***
     * 验证字符串是否是指定格式
     * @param str 待验证的字符串
     * @param patternS 正则表达式
     */
    public static Boolean matcher(String str, String patternS) {
        return isNotBlank(str) && Pattern.compile(patternS).matcher(str).matches();
    }

    /**
     * 获取指定字符(支持正则表达)在字符串的索引
     *
     * @param str 待查找的字符串
     * @param patternS 正则表达式
     * @return 索引，-1表示没有找到
     */
    public static int indexOf(String str, String patternS) {
//        patternS = "[1-9]{3}";
        var matcher = Pattern.compile(patternS).matcher(str);
        if (matcher.find()) {
            return matcher.start();
        }
        return -1;
    }


    /**
     * 验证字符串是否是数字，包括负数，小数
     */
    public static Boolean isNumeric(String str) {
        //Pattern pattern = Pattern.compile("^-?[0-9]+"); //这个也行
        return matcher(str, "^-?\\d+(\\.\\d+)?$");
    }

    /**
     * 验证字符串是否是正整数
     */
    public static Boolean isPositiveInt(String str) {
        return matcher(str, "^[0-9]*$");
    }

    /**
     * 验证字符串是否是十六进制数-正
     */
    public static Boolean isHex(String str) {
        return matcher(str, "^[A-Fa-f0-9]*$");
    }

    /*验证字符串是否是通用的code允许的字符。大小写字母、数字、下划线*/
    public static boolean validateCode(String str) {
        return matcher(str, "^[A-Za-z0-9_]*$");
    }

    /*验证字符串是否是通用的name允许的字符。大小写字母、数字、下划线、中文*/
    @SuppressWarnings("UnnecessaryUnicodeEscape")
    public static boolean validateName(String str) {
        return matcher(str, "^[A-Za-z0-9_\u4e00-\u9fa5]*$");
    }

    /**
     * 随机生成6位数(字母加数字)
     */
    public static String random6() {
        return random(6);
    }

    /*生成随机数(大小写字母加数字)*/
    public static String random(int digits) {
        var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var result = new StringBuilder();
        var random = new Random();
        var length = str.length();
        IntStream.range(0,digits).forEach(i -> result.append(str.charAt(random.nextInt(length))));
        return result.toString();
    }

    public static String randomNumber(int digits) {
        var str = "0123456789";
        var random = new Random();
        var length = str.length();
        var result = new StringBuilder();
        for (int i = 0; i < digits; i++) {
            result.append(str.charAt(random.nextInt(length)));
        }
        return result.toString();
//        return IntStream.range(0, digits).mapToObj(i -> String.valueOf(str.charAt(random.nextInt(length)))).collect(Collectors.joining());
//        IntStream.range(0,digits).forEach(i -> result.append(str.charAt(random.nextInt(length))));
    }


    public static String random8Hex() {
        var str = "ABCDEF0123456789";
        var result = new StringBuilder();
        var random = new Random();
        var length = str.length();
        Stream.iterate(0, i -> i + 1).limit(8).forEach(i -> result.append(str.charAt(random.nextInt(length))));
        return result.toString();
    }


    public static String randomExtend(int digits) {
        String randomFactor1 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_@%";
        var random = new Random();
        var length = randomFactor1.length();
        return IntStream.range(0, digits).boxed()
                .map(i -> String.valueOf(randomFactor1.charAt(random.nextInt(length))))
                .collect(Collectors.joining());
    }

    public static String randomHex(int digists) {
        return String.format("%0" + digists + "X", (int) (Math.random() * 256));
    }

    public static String join(String msg, Object... pars) {
        if (msg == null || !msg.contains("{}") || ListUtil.isEmpty(pars)) {
            return msg;
        }
        for (Object par : pars) {
            msg = msg.replaceFirst("\\{}", par == null ? "" : par.toString());
        }
        return msg;
    }

    public static String join(String[] values, String delimiter) {
        if (ListUtil.isEmpty(values)) {
            return "";
        }
        return String.join(delimiter, values);
//       return Arrays.stream(values).collect(Collectors.joining(delimiter));
    }

    public static String join(String[] values) {
        return join(values, ",");
    }


    public static String println(String msg, Object... pars) {
        String result = join(msg, pars);
        System.out.println(result);
        return result;
    }

    /**
     * 金额转换
     * 0.22 转换22
     * 即0.22元换成22分
     */
    public static Integer strMoney2Int(String money) {
        String[] ss = money.split("\\.");
        int result = 0;
        if (ss.length == 1) {
            result = Integer.parseInt(money) * 100;
        } else if (ss.length == 2) {
            result = Integer.parseInt(ss[0]) * 100 + Integer.parseInt(ss[1]);
        }
        return result;
    }

    public static Boolean equalOr(String str, String... compares) {
        var bank1 = isBlank(str);
        var bank2 = ListUtil.isEmpty(compares);
        if (bank1 && bank2) {
            return true;
        }
        if (bank1 || bank2) {
            return false;
        }
        return Arrays.asList(compares).contains(str);
    }

    @Deprecated
    public static boolean equal(String a,String b){
        return Objects.equals(a, b);
    }

    /*截取字符串后n位*/
    public static String getSuffix(String str, int limit) {
        if (str == null || str.length() <= limit) {
            return str;
        }
        return str.substring(str.length() - limit);
    }


}
